﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using App1AppHandler;
using System.Drawing;
using System.Timers;
using Reborn_WorldServer;

namespace Reborn_Server.App1AppHandler
{
    public class Spell_Burn3 : AreaSpell
    {
        public Spell_Burn3() 
        {
            DurationLow = 3;
            DurationHigh = 6;
        }

        private int BaseIceDamageLow = 80;
        private int BaseIceDamageHigh = 130;

        private int BaseFireDamageLow = 120;
        private int BaseFireDamageHigh = 160;

        public int DamageLow = 50;
        public int DamageHigh = 70;

        public override bool hasCustomTarget(SpellIcon sIcon)
        {
            if (sIcon.Skill == "Ice")
                return true;
            else
                return base.hasCustomTarget(sIcon);
        }


        private int choosenMapX = -1;
        private int choosenMapY = -1;
        public override bool hasValidTarget(SpellIcon sIcon, Creature creature, List<Point> hiddenList)
        {
            if (CreatureAI.hexIsDangerous(creature, creature.currentMapItem))
                return false;

            List<CreatureBase> targetCreatures = new List<CreatureBase>();

            foreach (MapItem mapitem in creature.currentMapItem.mapItemsWithin4)
            {
                if (CreatureAI.isHidden(mapitem.MapX, mapitem.MapY, hiddenList) == false)
                {
                    foreach (CreatureBase creatureBase in mapitem.CreaturesBases)
                    {
                        if (creatureBase.Faction != creature.Faction && mapitem.TerrainType != "Water" && creatureBase.HP > 0 && creatureBase.CanSeeMe(creature))
                            targetCreatures.Add(creatureBase);
                    }
                }
            }

            if (targetCreatures.Count > 0)
            {
                CreatureBase choosenTarget = targetCreatures[Managers.GameHandler.random.Next(0, targetCreatures.Count)];

                //targetCreatures = creature.hateManager.prioritizeList(targetCreatures);
                choosenMapX = choosenTarget.MapX;
                choosenMapY = choosenTarget.MapY;

                return true;
            }

            return false;
        }

        public void PositionCast(SpellIcon _spellIcon, CreatureBase myCreatureBase, int CastLevel, int MapX, int MapY)
        {
            if (choosenMapX != -1)
                MapX = choosenMapX;
            if (choosenMapY != -1)
                MapY = choosenMapY;

            List<MapItem> MapItemsWithin12;
            base.InitializeInstantCast(myCreatureBase, CastLevel, _spellIcon, MapX, MapY, out MapItemsWithin12);

            if (spellIcon.Skill == "Fire")
            {
                DamageLow = BaseFireDamageLow;
                DamageHigh = BaseFireDamageHigh;
            }
            else if (spellIcon.Skill == "Ice")
            {
                DamageLow = BaseIceDamageLow;
                DamageHigh = BaseIceDamageHigh;
            }

            DamageLow = SkillManager.AdjustForCombat(CastLevel, DamageLow, myCreatureBase.IntelligenceTotal);
            DamageHigh = SkillManager.AdjustForCombat(CastLevel, DamageHigh, myCreatureBase.IntelligenceTotal);

            MainCast(myCreatureBase, CastMapX, CastMapY, MapItemsWithin12);
        }

        public void CreatureCast(SpellIcon _spellIcon, CreatureBase myCreatureBase, int CastLevel, int MapX, int MapY)
        {
            List<MapItem> MapItemsWithin12;
            base.InitializeInstantCast(myCreatureBase, CastLevel, _spellIcon, MapX, MapY, out MapItemsWithin12);

            myCreatureBase.Mana = myCreatureBase.Mana - _spellIcon.ManaCost;
            myCreatureBase.WarmSpell = null;

            if (spellIcon.Skill == "Fire")
            {
                DamageLow = BaseFireDamageLow;
                DamageHigh = BaseFireDamageHigh;
            }
            else if (spellIcon.Skill == "Ice")
            {
                DamageLow = BaseIceDamageLow;
                DamageHigh = BaseIceDamageHigh;
            }

            DamageLow = SkillManager.AdjustForCombat(CastLevel, DamageLow, myCreatureBase.IntelligenceTotal);
            DamageHigh = SkillManager.AdjustForCombat(CastLevel, DamageHigh, myCreatureBase.IntelligenceTotal);

            MainCast(myCreatureBase, CastMapX, CastMapY, MapItemsWithin12);
        }

        private void MainCast(CreatureBase myCreatureBase, int MapX, int MapY, List<MapItem> MapItemsWithin12)
        {

            CastMapX = MapX;
            CastMapY = MapY;

            List<Point> HiddenList = CreatureAI.FindHidden(CastMapX, CastMapY, MapItemsWithin12);

            List<Character> CharactersWithinUpdateRange = new List<Character>();
            foreach (MapItem mapitem in MapItemsWithin12)
            {
                foreach (CreatureBase creatureBase in mapitem.CreaturesBases)
                {
                    if (creatureBase is Character)
                        CharactersWithinUpdateRange.Add((Character)creatureBase);
                }
                //Add this spell to each mapitem in range & record mapitem for timer

                int range = 0;
                if (spellIcon.Name == "Burn 3" || spellIcon.Name == "Hail Storm 3")
                    range = 4;
                else if (spellIcon.Name == "Burn 2" || spellIcon.Name == "Hail Storm 2")
                    range = 1;

                if (Math.Abs(mapitem.MapX - CastMapX) <= range && Math.Abs(mapitem.MapY - CastMapY) <= range && CreatureAI.isHidden(mapitem.MapX, mapitem.MapY, HiddenList) == false &&
                    mapitem.Motion > 0 && mapitem.TerrainType != "Water" && mapitem.Transparent == true)
                {
                    if (spellIcon.Skill == "Fire")
                    {
                        foreach (Spell spell in mapitem.SpellLayer0)
                        {
                            if (spell.spellIcon.StackType != "" && spell.spellIcon.StackType == spellIcon.StackType)
                            {
                                mapitem.SpellLayer0.Remove(spell);
                                break;
                            }
                        }
                        mapitem.SpellLayer0.Add(this);
                    }
                    else if (spellIcon.Skill == "Ice")
                    {
                        foreach (Spell spell in mapitem.SpellLayer1)
                        {
                            if (spell.spellIcon.StackType != "" && spell.spellIcon.StackType == spellIcon.StackType)
                            {
                                mapitem.SpellLayer1.Remove(spell);
                                break;
                            }
                        }
                        mapitem.SpellLayer1.Add(this);
                    }

                    MapItems.Add(mapitem);
                }
            }
            List<CreatureBase> creaturesToDamage = new List<CreatureBase>();
            foreach (MapItem mapitem in MapItems)
            {
                foreach (CreatureBase creatureBase in mapitem.CreaturesBases)
                {
                    if (creatureBase.HP < 1)
                        continue;

                    creaturesToDamage.Add(creatureBase);
                }
            }
            foreach (CreatureBase creatureBase in creaturesToDamage)
            {
                if (creatureBase.HP < 1)
                    continue;


                //Get the creature we would give a SD flag to.
                Character characterToApplyFlag = null;

                //If the creature we're casting at is a pet, get its master
                Pet_Controller pc = creatureBase.petController;
                //Has pet controller, check if master is character
                if (pc != null && pc.MasterCreature is Character)
                    characterToApplyFlag = (Character)pc.MasterCreature;
                //No pet controller, check if target is character
                else if (pc == null && creatureBase is Character)
                    characterToApplyFlag = (Character)creatureBase;

                //If we're attacking a player, and we dont have a flag on them, give them a flag on us.
                if (characterToApplyFlag != null &&
                    myCreatureBase is Character &&
                    characterToApplyFlag != myCreatureBase &&
                    myCreatureBase.hateManager.GetCreatureHateInfo(characterToApplyFlag) == null &&
                    spellIcon.Offensive == true)
                {
                    Character charToAttack = (Character)characterToApplyFlag;
                    if (charToAttack.friendsManager.hasNoSDFlag(CastingCharacterID) == false)
                    {
                        if (charToAttack.hateManager.GetCreatureHateInfo(myCreatureBase) == null)
                        {
                            charToAttack.SendMessage("You have been ATTACKED by " + myCreatureBase.Name + "!", "damaged");
                            charToAttack.PlaySound("Ding", charToAttack.MapX, charToAttack.MapY);

                            charToAttack.hateManager.UpdateList(myCreatureBase, 0);

                            charToAttack.AddMapItem(myCreatureBase.currentMapItem);
                        }
                        else
                            charToAttack.hateManager.UpdateList(myCreatureBase, 0);
                    }
                }

                int dmg = Managers.GameHandler.random.Next(DamageLow, DamageHigh + 1);

                int reducedDamage = creatureBase.CalculateGetSpellDamagePerResists(dmg, this.spellIcon.Skill);
                int absorbedDamage;
                creatureBase.InflictSpellDamage(reducedDamage, CastingCharacterID, CastingCreatureGUID, spellIcon.Skill, out absorbedDamage);
                creatureBase.Update_Character();

                reducedDamage = reducedDamage - absorbedDamage;

                string targetMessageText = "";
                string casterMessageText = "";
                if (spellIcon.Skill == "Ice")
                {
                    targetMessageText = "You are freezing! (" + reducedDamage.ToString() + ")";
                    casterMessageText = "You freeze " + creatureBase.Name + " (" + reducedDamage.ToString() + ")";
                }
                else if (spellIcon.Skill == "Fire")
                {
                    targetMessageText = "You are burning! (" + reducedDamage.ToString() + ")";
                    casterMessageText = "You burn " + creatureBase.Name + " (" + reducedDamage.ToString() + ")";
                }

                if (absorbedDamage != 0 && targetMessageText != "")
                    targetMessageText = targetMessageText + " ABSORBED " + absorbedDamage.ToString();
                if (absorbedDamage != 0 && casterMessageText != "")
                    casterMessageText = casterMessageText + " ABSORBED " + absorbedDamage.ToString();

                if (targetMessageText != "")
                    creatureBase.SendMessage(targetMessageText, "spelldamaged");
                if (casterMessageText != "")
                    Managers.GameHandler.TrySendMessage(CastingCharacterID, casterMessageText, "spelldamage");
            }
            foreach (MapItem mapitem in MapItems)
            {
                for (int x = 0; x < mapitem.CreaturesBases.Count; x++)
                {
                    CreatureBase creaturebase = (CreatureBase)mapitem.CreaturesBases[x];

                    if (creaturebase.HP < 1)
                    {
                        if (!(creaturebase is Character))
                        {
                            mapitem.CreaturesBases.RemoveAt(x);
                            x--;
                        }
                    }
                }
            }

            if (MapItems.Count > 0)
            {
                foreach (Character character in CharactersWithinUpdateRange)
                {
                    character.AddMapItems(MapItems, false);

                    if (spellIcon.Skill == "Fire")
                        character.PlaySound("FireBall", CastMapX, CastMapY);
                }
            }

            //Start Spell Timer
            spellTimer.Start();
        }


        public void Cast(CreatureBase myCreatureBase, int CastLevel, List<string> MoveList)
        {
            List<MapItem> MapItemsWithin12;
            if (base.InitializeCast(myCreatureBase, CastLevel, MoveList, out MapItemsWithin12) == false)
                return;

            if (spellIcon.Skill == "Fire")
            {
                DamageLow = BaseFireDamageLow;
                DamageHigh = BaseFireDamageHigh;
            }
            else if (spellIcon.Skill == "Ice")
            {
                DamageLow = BaseIceDamageLow;
                DamageHigh = BaseIceDamageHigh;
            }

            DamageLow = SkillManager.AdjustForCombat(CastLevel, DamageLow, myCreatureBase.IntelligenceTotal);
            DamageHigh = SkillManager.AdjustForCombat(CastLevel, DamageHigh, myCreatureBase.IntelligenceTotal);

            MainCast(myCreatureBase, CastMapX, CastMapY, MapItemsWithin12);
        }

        protected override void SpellTimer_Expired(object source, ElapsedEventArgs e)
        {
            TimerCounter = TimerCounter + 1;

            //Get MapLock
            LockItem MapLock = Managers.GameHandler.GetLockItem(MapID, Instance);

            //Lock MapLock
            lock (MapLock.LockObj)
            {
                Map CurrentMap = Managers.GameHandler.GetMap(MapID, Instance);

                for (int x = 0; x < MapItems.Count; x++)
                {
                    MapItem mapItem = MapItems[x];
                    if (mapItem.SpellLayer1.Contains(this) == false && mapItem.SpellLayer0.Contains(this) == false)
                    {
                        MapItems.RemoveAt(x);
                        x--;
                    }
                }

                //Stop Running if no mapitems
                if (MapItems.Count == 0)
                    return;

                List<MapItem> MapItemsToUpdate = new List<MapItem>();

                foreach (MapItem mapitem in MapItems)
                {
                    bool foundSpell = false;
                    if (spellIcon.Skill == "Fire" && mapitem.SpellLayer0.Contains(this))
                        foundSpell = true;
                    else if (spellIcon.Skill == "Ice" && mapitem.SpellLayer1.Contains(this))
                        foundSpell = true;

                    if (foundSpell == false)
                        continue;

                    if (TimerCounter >= DurationLow)
                    {
                        if (mapitem.MapX != CastMapX || mapitem.MapY != CastMapY)
                        {
                            int RemoveSpell = Managers.GameHandler.random.Next(-1, DurationHigh - TimerCounter);
                            if (RemoveSpell == -1)
                            {
                                if (spellIcon.Skill == "Fire")
                                    mapitem.SpellLayer0.Remove(this);
                                else if (spellIcon.Skill == "Ice")
                                    mapitem.SpellLayer1.Remove(this);

                                if (MapItemsToUpdate.Contains(mapitem) == false)
                                    MapItemsToUpdate.Add(mapitem);

                                continue;
                            }
                        }
                        else if (TimerCounter >= DurationHigh)
                        {
                            if (spellIcon.Skill == "Fire")
                                mapitem.SpellLayer0.Remove(this);
                            else if (spellIcon.Skill == "Ice")
                                mapitem.SpellLayer1.Remove(this);

                            if (MapItemsToUpdate.Contains(mapitem) == false)
                                MapItemsToUpdate.Add(mapitem);

                            continue;
                        }
                    }
                    if (spellIcon.Skill == "Fire")
                    {
                        Corpse corpse = CurrentMap.LootMngr.GetFirstCorpse(mapitem.MapX, mapitem.MapY);
                        if (corpse != null)
                        {
                            Managers.GameHandler.Corpse_Roll(null, MapID, Instance, mapitem.MapX, mapitem.MapY, corpse.GameUID);

                            if (MapItemsToUpdate.Contains(mapitem) == false)
                                MapItemsToUpdate.Add(mapitem);
                        }
                        else
                        {
                            CorpseCharacter charCorpse = CurrentMap.LootMngr.GetFirstCharacterCorpse(mapitem.MapX, mapitem.MapY);
                            if (charCorpse != null)
                            {
                                Managers.GameHandler.Corpse_Roll(null, MapID, Instance, mapitem.MapX, mapitem.MapY, charCorpse.GameUID);
                                Managers.GameHandler.Resurrect(charCorpse.MyCharacter);

                                if (MapItemsToUpdate.Contains(mapitem) == false)
                                    MapItemsToUpdate.Add(mapitem);
                            }
                        }
                    }
                }

                List<Character> CharsToUpdate = new List<Character>();
                //Send Updated Hexes to all characters within 4 of any hex effected
                foreach (MapItem mapitem in CastMapItem.mapItemsWithin12)
                {
                    foreach (MapItem mitem in MapItems)
                    {
                        if (Math.Abs(mitem.MapX - mapitem.MapX) <= 4 && Math.Abs(mitem.MapY - mapitem.MapY) <= 4)
                        {
                            foreach (CreatureBase creatureBase in mapitem.CreaturesBases)
                            {
                                if (creatureBase is Character)
                                    CharsToUpdate.Add((Character)creatureBase);
                            }
                            break;
                        }
                    }
                }

                List<CreatureBase> creaturesToDamage = new List<CreatureBase>();
                foreach (MapItem mapitem in MapItems)
                {
                    foreach (CreatureBase creatureBase in mapitem.CreaturesBases)
                    {
                        if (creatureBase.HP > 1)
                            creaturesToDamage.Add(creatureBase);
                    }
                }

                foreach (CreatureBase creatureBase in creaturesToDamage)
                {
                    if (MapItemsToUpdate.Contains(creatureBase.currentMapItem) == false)
                        MapItemsToUpdate.Add(creatureBase.currentMapItem);

                    int dmg = Managers.GameHandler.random.Next(DamageLow, DamageHigh + 1);
                    int reducedDamage = creatureBase.CalculateGetSpellDamagePerResists(dmg, this.spellIcon.Skill);
                    int absorbedDamage;
                    creatureBase.InflictSpellDamage(reducedDamage, CastingCharacterID, CastingCreatureGUID, spellIcon.Skill, out absorbedDamage);
                    creatureBase.Update_Character();

                    reducedDamage = reducedDamage - absorbedDamage;

                    string targetMessageText = "";
                    string casterMessageText = "";
                    if (spellIcon.Skill == "Ice")
                    {
                        targetMessageText = "You are freezing! (" + reducedDamage.ToString() + ")";
                        casterMessageText = "You freeze " + creatureBase.Name + " (" + reducedDamage.ToString() + ")";
                    }
                    else if (spellIcon.Skill == "Fire")
                    {
                        targetMessageText = "You are burning! (" + reducedDamage.ToString() + ")";
                        casterMessageText = "You burn " + creatureBase.Name + " (" + reducedDamage.ToString() + ")";
                    }

                    if (absorbedDamage != 0 && targetMessageText != "")
                        targetMessageText = targetMessageText + " ABSORBED " + absorbedDamage.ToString();
                    if (absorbedDamage != 0 && casterMessageText != "")
                        casterMessageText = casterMessageText + " ABSORBED " + absorbedDamage.ToString();

                    if (targetMessageText != "")
                        creatureBase.SendMessage(targetMessageText, "spelldamaged");
                    if (casterMessageText != "")
                        Managers.GameHandler.TrySendMessage(CastingCharacterID, casterMessageText, "spelldamage");
                }

                foreach (MapItem mapitem in MapItemsToUpdate)
                {
                    //Remove Creatures
                    bool Complete = false;
                    while (Complete == false)
                    {
                        int count = 0;
                        if (mapitem.CreaturesBases.Count == 0)
                            Complete = true;
                        foreach (CreatureBase creatureBase in mapitem.CreaturesBases)
                        {
                            count = count + 1;
                            if (creatureBase.HP < 1 && !(creatureBase is Character))
                            {
                                mapitem.CreaturesBases.Remove(creatureBase);
                                break;
                            }
                            if (count == mapitem.CreaturesBases.Count)
                            {
                                Complete = true;
                            }
                        }
                    }
                }
                foreach (Character character in CharsToUpdate)
                {
                    character.AddMapItems(MapItemsToUpdate, false);
                }
            
            }//End Lock

            spellTimer.Start();
        }

    }
}
